import { useControlController, useNamespace } from '@ibiz-template/vue3-util';
import { defineComponent, PropType, ref, VNode, watch } from 'vue';
import { ILayoutPanel, ISysCalendar } from '@ibiz/model-core';
import './calendar.scss';
import {
  CalendarController,
  ICalendarItemData,
  IControlProvider,
} from '@ibiz-template/runtime';
import dayjs from 'dayjs';

export const CalendarControl = defineComponent({
  name: 'IBizCalendarControl',
  props: {
    modelData: { type: Object as PropType<ISysCalendar>, required: true },
    context: { type: Object as PropType<IContext>, required: true },
    params: { type: Object as PropType<IParams>, default: () => ({}) },
    provider: { type: Object as PropType<IControlProvider> },
    mdctrlActiveMode: { type: Number, default: undefined },
    loadDefault: { type: Boolean, default: true },
  },
  setup() {
    const c = useControlController(
      (...args) => new CalendarController(...args),
    );
    const ns = useNamespace(`control-${c.model.controlType!.toLowerCase()}`);
    const calendarRef = ref<IData>();

    const popoverVisible = ref(false);

    const selectDate = (tag: string): void => {
      if (!calendarRef.value) return;
      calendarRef.value.selectDate(tag);
    };

    // 数据激活时关闭气泡
    c.evt.on('onActive', () => {
      popoverVisible.value = false;
    });

    watch(
      () => c.state.selectedDate,
      (oldVal: Date, newVal: Date) => {
        const oldDateString = dayjs(oldVal).format('YYYY-MM');
        const newDateString = dayjs(newVal).format('YYYY-MM');
        // 月份相同不加载数据
        if (oldDateString === newDateString) {
          return;
        }
        c.load();
      },
    );

    /**
     * 计算数据项样式
     *
     * @author zk
     * @date 2023-08-08 11:08:29
     * @param {ICalendarItemData} data
     * @return {*}  {IData}
     */
    const calcItemStyle = (data: ICalendarItemData): IData => {
      return {
        color: data.color,
        backgroundColor: data.bkColor,
      };
    };

    return {
      c,
      ns,
      calendarRef,
      popoverVisible,
      selectDate,
      calcItemStyle,
    };
  },
  render() {
    // 绘制项布局面板
    const renderPanelItem = (
      item: ICalendarItemData,
      modelData: ILayoutPanel,
    ): VNode => {
      const { context, params } = this.c;
      // 是否选中数据
      const findIndex = this.c.state.selectedData.findIndex(data => {
        return data.deData.srfkey === item.deData.srfkey;
      });
      const itemClass = [
        this.ns.b('item'),
        this.ns.is('active', findIndex !== -1),
      ];
      const style = this.calcItemStyle(item);
      return (
        <iBizControlShell
          class={itemClass}
          data={item.deData}
          modelData={modelData}
          context={context}
          params={params}
          style={style}
          onClick={(e: MouseEvent): Promise<void> => {
            e.stopPropagation();
            return this.c.onRowClick(item);
          }}
          onDblclick={(e: MouseEvent): Promise<void> => {
            e.stopPropagation();
            return this.c.onDbRowClick(item);
          }}
        ></iBizControlShell>
      );
    };

    // 绘制默认列表项
    const renderDefaultItem = (item: ICalendarItemData): VNode => {
      // 是否选中数据
      const findIndex = this.c.state.selectedData.findIndex(data => {
        return data.deData.srfkey === item.deData.srfkey;
      });
      const itemClass = [
        this.ns.b('item'),
        this.ns.is('active', findIndex !== -1),
      ];
      const style = this.calcItemStyle(item);
      return (
        <div
          class={itemClass}
          key={item.deData.srfkey}
          style={style}
          title={item.tips || item.text}
          onClick={(): Promise<void> => this.c.onRowClick(item)}
          onDblclick={(): Promise<void> => this.c.onDbRowClick(item)}
        >
          {item.text}
        </div>
      );
    };

    /**
     * 绘制日历项
     *
     * @param {ICalendarItemData} item
     * @return {*}
     */
    const renderCalendarItem = (item: ICalendarItemData) => {
      const model = this.c.model.sysCalendarItems?.find(calendarItems => {
        return item.itemType === calendarItems.itemType;
      });
      const panel = model!.layoutPanel;
      return panel ? renderPanelItem(item, panel) : renderDefaultItem(item);
    };

    /**
     * 绘制日历列表
     *
     * @author zk
     * @date 2023-08-08 02:08:34
     * @param {ICalendarItemData[]} items
     * @param {ISysCalendarItem} model
     * @return {*}  {VNode[]}
     */
    const renderCalendarList = (items: ICalendarItemData[]): VNode[] => {
      if (items.length > 1) {
        return [
          renderCalendarItem(items[0]),
          <el-popover trigger='click' v-model:visible={this.popoverVisible}>
            {{
              reference: () => {
                return (
                  <span class={this.ns.b('more')}>{`+${
                    items.length - 1
                  } ${ibiz.i18n.t('app.more')}...`}</span>
                );
              },
              default: () => {
                return items.map(item => {
                  return renderCalendarItem(item);
                });
              },
            }}
          </el-popover>,
        ];
      }
      return items.map(item => {
        return renderCalendarItem(item);
      });
    };

    /**
     * 绘制日历项
     *
     * @author zk
     * @date 2023-08-08 02:08:26
     * @return {*}  {VNode}
     */
    const renderCalendarItems = (date: Date): VNode[] => {
      const dateString = dayjs(date).format('YYYY-MM-DD');
      const items = this.c.state.items.filter((item: ICalendarItemData) => {
        const begin = new Date(item.beginTime);
        return dateString === dayjs(begin).format('YYYY-MM-DD');
      });
      return renderCalendarList(items);
    };

    /**
     * 绘制默认的日历
     * @return {*}
     * @author: zhujiamin
     * @Date: 2023-11-22 14:18:10
     */
    const renderElCalender = () => {
      return (
        <div class={this.ns.b('content')}>
          <el-calendar v-model={this.c.state.selectedDate} ref='calendarRef'>
            {{
              header: ({ date }: { date: string }): VNode[] => {
                return [
                  <span class={this.ns.b('content-title')}>{date}</span>,
                  <div class={this.ns.b('content-header')}>
                    <el-date-picker
                      v-model={this.c.state.selectedDate}
                      type='month'
                    />
                    <el-button-group>
                      <el-button
                        onClick={(): void => {
                          this.selectDate('prev-year');
                        }}
                      >
                        {ibiz.i18n.t('control.calendar.lastYear')}
                      </el-button>
                      <el-button
                        onClick={(): void => {
                          this.selectDate('prev-month');
                        }}
                      >
                        {ibiz.i18n.t('control.calendar.lastMonth')}
                      </el-button>
                      <el-button
                        onClick={(): void => {
                          this.selectDate('today');
                        }}
                      >
                        {ibiz.i18n.t('control.calendar.today')}
                      </el-button>
                      <el-button
                        onClick={(): void => {
                          this.selectDate('next-month');
                        }}
                      >
                        {ibiz.i18n.t('control.calendar.nextMonth')}
                      </el-button>
                      <el-button
                        onClick={(): void => {
                          this.selectDate('next-year');
                        }}
                      >
                        {ibiz.i18n.t('control.calendar.nextYear')}
                      </el-button>
                    </el-button-group>
                  </div>,
                  <div class={this.ns.b('legend')}>
                    {this.c.model.sysCalendarItems?.map(calendarItem => {
                      let label = calendarItem.name!;
                      if (calendarItem.nameLanguageRes) {
                        label = ibiz.i18n.t(
                          calendarItem.nameLanguageRes.lanResTag!,
                          calendarItem.name,
                        );
                      }
                      return (
                        <div class={this.ns.e('calendar-item')}>
                          <div
                            class={this.ns.e('icon')}
                            style={{
                              background: calendarItem.bkcolor,
                              color: calendarItem.color,
                            }}
                          ></div>
                          {label}
                        </div>
                      );
                    })}
                  </div>,
                ];
              },
              'date-cell': ({ data }: { data: IData }): VNode => {
                const { date } = data;
                return (
                  <div class={this.ns.b('day')}>
                    <p class={this.ns.b('date-text')}>{date.getDate()}</p>
                    <div class={this.ns.b('items')}>
                      {renderCalendarItems(date)}
                    </div>
                  </div>
                );
              },
            }}
          </el-calendar>
        </div>
      );
    };

    /**
     * 无数据
     * @param {*} VNode
     * @return {*}
     * @author: zhujiamin
     * @Date: 2023-11-22 14:46:37
     */
    const renderNoData = (): VNode | false => {
      // 未加载不显示无数据
      const { isLoaded } = this.c.state;
      return (
        isLoaded && (
          <iBizNoData
            text={this.c.model.emptyText}
            emptyTextLanguageRes={this.c.model.emptyTextLanguageRes}
          ></iBizNoData>
        )
      );
    };

    /**
     * 绘制时间轴日历
     * @return {*}
     * @author: zhujiamin
     * @Date: 2023-11-22 14:18:25
     */
    const renderTimeLine = () => {
      return (
        <div class={this.ns.b('timeline-content')}>
          <el-timeline>
            {this.c.state.items.length > 0
              ? this.c.state.items.map(item => {
                  const model = this.c.model.sysCalendarItems?.find(
                    calendarItems => {
                      return item.itemType === calendarItems.itemType;
                    },
                  );
                  return (
                    <el-timeline-item
                      key={item.id}
                      placement='top'
                      color={item.bkColor}
                      timestamp={item.beginTime}
                    >
                      {model?.layoutPanel
                        ? renderPanelItem(item, model.layoutPanel)
                        : renderDefaultItem(item)}
                    </el-timeline-item>
                  );
                })
              : renderNoData()}
          </el-timeline>
        </div>
      );
    };

    const renderCalendar = () => {
      switch (this.c.model.calendarStyle) {
        case 'TIMELINE':
          return renderTimeLine();
          break;
        default:
          return renderElCalender();
          break;
      }
    };

    return (
      <iBizControlBase controller={this.c}>{renderCalendar()}</iBizControlBase>
    );
  },
});
